<template>
	<div class="at-form-item" :class="{
    'is-error': validateState === 'error',
    'is-validating': validateState === 'validating',
    'is-required': isRequired || required
  }">
    <label :for="prop" class="at-form-item__label" v-bind:style="labelStyle" v-if="label || $slots.label">
      <slot name="label">
				<span
					:class="[project === 'mh' && validateState === 'error' ? 'at-form-item__label-error' : '']"
				  >
					{{label + form.labelSuffix}}
				</span>
			</slot>
    </label>
    <div class="at-form-item__content" :class="[project === 'mh' && validateState === 'error' ? 'at-form-item__label-error' : '']" v-bind:style="contentStyle">
			<slot></slot>
      <transition name="at-zoom-in-top">
				<div v-if="project==='mh'">
					<div class="at-form-item__error" v-if="validateState === 'error' && showMessage && form.showMessage">{{validateMessage}}</div>
				</div>
				<div v-else>
					<div class="at-form-item__error" v-if="validateState === 'error' && showMessage && form.showMessage"><img src="../../theme-default/assets/form/01.png" class="at-form-item__error_img">&nbsp;&nbsp;{{validateMessage}}</div>
				</div>
      </transition>
    </div>
  </div>
</template>

<script>
/**
 *@author 陈杨
 */
    import AsyncValidator from 'async-validator';
    import emitter from '../../common/mixins/emitter';

    function noop() {}

    function getPropByPath(obj, path) {
      let tempObj = obj;
      path = path.replace(/\[(\w+)\]/g, '.$1');
      path = path.replace(/^\./, '');

      let keyArr = path.split('.');
      let i = 0;

    for (let len = keyArr.length; i < len - 1; ++i) {
		let key = keyArr[i];
		if (key in tempObj) {
			tempObj = tempObj[key];
		} else {
			throw new Error('please transfer a valid prop path to form item!');
		}
	}
		return {
			o: tempObj,
			k: keyArr[i],
			v: tempObj[keyArr[i]]
		};
	}
	export default{
		name:"at-form-item",

		componentName: "AtFormItem",

		mixins: [emitter],

		props: {
/**
 *@type {string} project 项目标识
 */
			project: String,
/**
 *@type {string} label 标签文本
 */
			label: String,
/**
 *@type {string} labelWidth 表单域标签的宽度
 */
			labelWidth: String,
/**
 *@type {string} prop 表单域model字段（在使用validate、resetFields方法的情况下，该属性是必填的）
 */
			prop: String,
/**
 *@type {Boolean} required 是否必填
 */
			required: Boolean,
/**
 *@type {Object,Array} rules 表单验证规则
 */
			rules: [Object, Array],
/**
 *@type {string} error 表单域验证错误信息
 */
			error: String,
/**
 *@type {string} validateStatus 标签文本
 */
			validateStatus: String,
/**
 *@type {Object} showMessage 是否显示校验错误信息
 */
			showMessage: {
				type: Boolean,
				default: true
			}
		},
		watch: {
/**
 *@param {string} value 自定义的错误信息
 *@description 获取自定义的错误信息，如果错误信息存在，则validateState为'error',否则为空
 */
			error(value) {
				this.validateMessage = value;
				this.validateState = value ? 'error' : '';
			},
/**
 *@param {string} value 自定义的错误状态
 *@description 获取自定义的错误状态
 */
			validateStatus(value) {
				this.validateState = value;
			}
		},
		computed: {
/**
 *@returns {Object} 表单域标签的样式：{}或者自定义的表单域标签宽度
 *@description 计算表单域标签的样式：如果labelPosition为'top',则返回{}；如果在使用组件时设置了label-width,则获取这个宽度
 */
	      labelStyle() {
	        var ret = {};
	        if (this.form.labelPosition === 'top') return ret;
	        var labelWidth = this.labelWidth || this.form.labelWidth;
	        if (labelWidth) {
	          ret.width = labelWidth;
	        }
	        return ret;
	      },
/**
 *@returns {Object} 表单域容器的样式：{}或者左外边距为自定义的表单域标签宽度
 *@description 计算表单域容器的样式：如果labelPosition为'top'或者设置了行内表单模式,或者没有设置标签文本，或者没有设置表单域标签的宽度则返回{}；如果在使用组件时设置了label-width,则获取这个宽度
 */
	      contentStyle() {
	        var ret = {};
	        const label = this.label;
	        if (this.form.labelPosition === 'top' || this.form.inline) return ret;
	        if (!label && !this.labelWidth && this.isNested) return ret;
	        var labelWidth = this.labelWidth || this.form.labelWidth;
	        if (labelWidth) {
	          ret.marginLeft = labelWidth;
	        }
	        return ret;
	      },
/**
 *@returns {Object} 父实例
 *@description 获取父实例，如果父实例的compontentName不为'ElForm',则再次向上一级获取父实例
 */
	      form() {
	        let parent = this.$parent;
	        let parentName = parent.$options.componentName;
	        while (parentName !== 'AtForm') {
	        	if (parentName === 'AtFormItem'){
	        		this.isNested = true;
	        	}
	        	parent = parent.$parent;
	        	parentName = parent.$options.componentName;
	        }
	        return parent;
	      },
/**
 *@type {string} newProp 新的prop值
 */
	      fieldValue: {
/**
 *@type {boolean}
 */
			cache: false,
/**
 *@returns {String} formitem中的组件中的值
 *@description 获取formitem中的组件中的值
 */
	        get() {
	          var model = this.form.model;
	          if (!model || !this.prop) { return; }

	          var path = this.prop;
	          if (path.indexOf(':') !== -1) {
	            path = path.replace(/:/, '.');
	          }
	          return getPropByPath(model, path).v;
	        }
		},
/**
 *@returns {boolean}
 *@description 计算当前formitem中的内容是否必填，如果自定义的rule中设置了isRequired字段，则返回true（必填），否则默认为false
 */
	      isRequired() {
	        let rules = this.getRules();
	        let isRequired = false;

	        if (rules && rules.length) {
	          rules.every(rule => {
	            if (rule.required) {
	              isRequired = true;
	              return false;
	            }
	            return true;
	          });
	        }
	        return isRequired;
	      }
	    },
		data: function () {
			return {
				validateState: '',
				validateMessage: '',
				validateDisabled: false,
				validator: {},
				isNested:false,
			}
		},
		methods: {
/**
 *@param {string} trigger formitem中属性的验证规则
 *@param {Object} callback 回调函数，默认为空函数
 *@description 调用AsyncValidator,对于表单中的值通过自定义的规则进行验证（内部封装了8种验证规则）
 */
	      validate(trigger, callback = noop) {
	        var rules = this.getFilteredRule(trigger);
	        if ((!rules || rules.length === 0) && !this._props.hasOwnProperty('required')) {
	          callback();
	          return true;
	        }

	        this.validateState = 'validating';

	        var descriptor = {};
	        descriptor[this.prop] = rules;

	        var validator = new AsyncValidator(descriptor);
	        var model = {};
	        model[this.prop] = this.fieldValue;

	        validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        if(this.prop=="ATEmail"){
	        	validator.rules["ATEmail"][0].validator=(rule, value, callback)=>{
		        var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
		        if (!value) {
		        	return callback(new Error('邮箱不能为空'));
		        }else{
			        setTimeout(() => {
			        if (reg.test(value)==false){
			          return callback(new Error('请输入正确格式邮箱'));
			        }else{
			          callback();
			        }
			       },1000)
		        }
		      }
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';
	          callback(this.validateMessage);
	        });
	        }else if(this.prop=="ATAge"){
	        	validator.rules["ATAge"][0].validator=(rule, value, callback) => {
		        if (!value) {
		          return callback(new Error('年龄不能为空'));
		        }
		        setTimeout(() => {
		          if (!Number.isInteger(value)) {
		            callback(new Error('请输入数字值'));
		          } else {
		            if (value < 18) {
		              callback(new Error('必须年满18岁'));
		            } else if(value > 100){
		              callback(new Error('请输入正确的年龄'))
		            }else {
		              callback();
		            }
		          }
		        }, 1000);
		      };
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        }else if(this.prop=="ATIp"){
	        	validator.rules["ATIp"][0].validator=(rule, value, callback)=>{
		        if (value === '') {
		          callback(new Error('ip不能为空'));
		        }
		        var reg=/^(?:(?:1[0-9][0-9]\.)|(?:2[0-4][0-9]\.)|(?:25[0-5]\.)|(?:[1-9][0-9]\.)|(?:[0-9]\.)){3}(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$/;
		        setTimeout(()=>{
		          if (reg.test(value)==false){
		            return callback(new Error('请输入正确格式的ip'));
		          }else{
		            callback();
		          }
		        },1000)
		      };
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        }else if(this.prop=="ATPerName"){
	        	validator.rules["ATPerName"][0].validator=(rule, value, callback)=>{
		        if(!value) {
		          return callback(new Error('此项为必填'));
		        }
		        setTimeout(()=>{
		          if(String(value).length>20||String(value).length<2){
		            callback(new Error('长度在 2 到 20 个字符之间'));
		          }else{
		            callback();
		          }
		        },1000)
		      };
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        }else if(this.prop=="ATUserName"){
	        	validator.rules["ATUserName"][0].validator=(rule, value, callback)=>{
		        if(!value) {
		          return callback(new Error('此项为必填'));
		        }
		        setTimeout(()=>{
		          if(String(value).length>16||String(value).length<3){
		            callback(new Error('长度在 3 到 16 个字符'));
		          }else{
		            var reg=/^[a-zA-Z0-9_]+$/;
		            if (reg.test(value)==false){
		              return callback(new Error('由字母数字下划线组成'));
		            }else{
		              callback();
		            }
		          }
		        },1000)
		      };
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        }else if(this.prop=="ATPhoneNum"){
	        	validator.rules["ATPhoneNum"][0].validator=(rule,value,callback)=>{
		        var reg=/^1[34578][0-9]{9}$/;
		        if(!value) {
		          return callback(new Error('手机号为必填,请输入手机号码'));
		        }
		        setTimeout(() => {
		        if (reg.test(value)==false){
		          return callback(new Error('请输入正确格式手机号码'));
		        }else{
		          callback();
		        }
		       },1000)
		      }
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        }else if(this.prop=="ATIdCard"){
	        	validator.rules["ATIdCard"][0].validator=(rule,value,callback)=>{
		        var reg=/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/;
		        if(!value) {
		          return callback(new Error('身份证号为必填,请输入身份证号码'));
		        }
		        setTimeout(() => {
		        if (reg.test(value)==false){
		          return callback(new Error('请输入正确格式身份证号码'));
		        }else{
		          callback();
		        }
		       },1000)
		      }
		      validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';

	          callback(this.validateMessage);
	        });
	        }else if(this.prop==="ATIpAdd"){
		      	validator.rules["ATIpAdd"][0].validator=(rule, value, callback)=>{
                if (value === [undefined,undefined,undefined,undefined]) {
                  callback(new Error('ip不能为空'));
                }
                var reg=/^(?:(?:1[0-9][0-9])|(?:2[0-4][0-9])|(?:25[0-5])|(?:[1-9][0-9])|(?:[0-9]))$/;
                setTimeout(()=>{
                  if ((reg.test(value[0])&&reg.test(value[1])&&reg.test(value[2])&&reg.test(value[3]))===false){
                    return callback(new Error('请输入正确格式的ip地址'));
                  }else{
                    callback();
                  }
                },1000)
              }
              validator.validate(model, { firstFields: true }, (errors, fields) => {
	          this.validateState = !errors ? 'success' : 'error';
	          this.validateMessage = errors ? errors[0].message : '';
	          callback(this.validateMessage);
		      })
           }
				},
		clearValidate() {
	        this.validateState = '';
	        this.validateMessage = '';
	        this.validateDisabled = false;
	      },
/**
 *@description 对于表单中的单个字段值进行重置并且移除校验结果
 */
	      resetField() {
	        this.validateState = '';
	        this.validateMessage = '';

	        let model = this.form.model;
	        let value = this.fieldValue;
	        let path = this.prop;
	        if (path.indexOf(':') !== -1) {
	          path = path.replace(/:/, '.');
	        }

	        let prop = getPropByPath(model, path);

	        if (Array.isArray(value)) {
	          this.validateDisabled = true;
	          prop.o[prop.k] = [].concat(this.initialValue);
	        } else {
	          this.validateDisabled = true;
	          prop.o[prop.k] = this.initialValue;
	        }
		},
/**
 *@description 获取校验规则（form内部的规则和用户自定义的规则）
 */
	      getRules() {
	        var formRules = this.form.rules;
	        var selfRules = this.rules;
	        var requiredRule = this._props.hasOwnProperty('required') ? { required:!!this.required } : [];

	        formRules = formRules ? formRules[this.prop] : [];

	        return [].concat(selfRules || formRules || []).concat(requiredRule);
		},
/**
 *@description 将规则里对于属性的验证过滤掉
 */
	      getFilteredRule(trigger) {
	        var rules = this.getRules();

	        return rules.filter(rule => {
	          return !rule.trigger || rule.trigger.indexOf(trigger) !== -1;
	        });
		},
/**
 *@description 对于属性规则中的'blur'进行验证
 */
	      onFieldBlur() {
	        this.validate('blur');
		},
/**
 *@description 对于属性规则中的'change'进行验证
 */
	      onFieldChange() {
	        if (this.validateDisabled) {
	          this.validateDisabled = false;
	          return;
	        }

	        this.validate('change');
	      }
	    },
        mounted() {
	      if (this.prop) {
	        this.dispatch('AtForm', 'at.form.addField', [this]);

	        let initialValue = this.fieldValue;
	        if (Array.isArray(initialValue)) {
	          initialValue = [].concat(initialValue);
	        }
	        Object.defineProperty(this, 'initialValue', {
	          value: initialValue
	        });

	        let rules = this.getRules();
	        if (rules.length || this._props.hasOwnProperty('required')) {
	          this.$on('at.form.blur', this.onFieldBlur);
	          this.$on('at.form.change', this.onFieldChange);
	        }
	      }
	    },
        beforeDestroy() {
	      this.dispatch('AtForm', 'at.form.removeField', [this]);
	    }
	}
</script>
<style>
</style>